package org.jeecg.modules.demo.student.controller;

import cn.hutool.core.date.DateTime;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.errors.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.jeecg.modules.demo.constant.BaseContext;
import org.jeecg.modules.demo.constant.papersStatus;
import org.jeecg.modules.demo.drfFile.domain.DrfFile;
import org.jeecg.modules.demo.drfFile.service.DrfFileService;
import org.jeecg.modules.demo.drfIndividualReview.service.IDrfIndividualReviewService;
import org.jeecg.modules.demo.drfNotice.service.IDrfNoticeService;
import org.jeecg.modules.demo.drfProblem.entity.DrfProblem;
import org.jeecg.modules.demo.drfProblem.service.IDrfProblemService;
import org.jeecg.modules.demo.drfStudent.entity.DrfStudent;
import org.jeecg.modules.demo.drfStudent.service.IDrfStudentService;
import org.jeecg.modules.demo.drfpapers.entity.DrfPapers;
import org.jeecg.modules.demo.drfpapers.service.IDrfPapersService;
import org.jeecg.modules.demo.drfusers.entity.DrfUsers;
import org.jeecg.modules.demo.drfusers.service.IDrfUsersService;
import org.jeecg.modules.demo.drfNotice.entity.DrfNotice;
import org.jeecg.modules.demo.pojo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import org.jeecg.modules.demo.student.service.MinIOService;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.io.EOFException;

@RestController
@RequestMapping("/drf/studentPortal")
@Slf4j
@Api(tags="盲审—学生端")
public class StudentController {

    @Autowired
    private IDrfPapersService drfPapersService;
    @Autowired
    private IDrfUsersService drfUsersService;
    @Autowired
    private MinIOService minIOService;
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private IDrfNoticeService drfNoticeService;
    @Autowired
    private DrfFileService drfFileService;
    @Autowired
    private IDrfStudentService drfStudentsService;
    @Autowired
    private IDrfIndividualReviewService drfIndividualReviewService;
    @Autowired
    private IDrfProblemService drfProblemService;

    /**
     * 添加学生信息
     */
    @ApiOperation("添加(修改)学生信息")
    @PostMapping("/addStudent")
    public Result<String> addStudent(@RequestBody studentDTO student) {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：添加(修改)学生信息");
        DrfStudent drfStudent = new DrfStudent();
        BeanUtils.copyProperties(student, drfStudent);
        drfStudent.setUserId(userId);
        drfStudentsService.updateById(drfStudent);
        if(student.getPhone() != null){
            drfUsers.setPhone(student.getPhone());
            drfUsers.setUpdatedTime(DateTime.now());
            drfUsersService.updateById(drfUsers);
        }
        return Result.success("添加(修改)成功");
    }

    /**
     * 修改论文信息接口
     */
    @ApiOperation("修改论文信息")
    @PostMapping("/updatePaper")
    public Result<String> updatePaper(@RequestBody paperDTO paper) {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：修改论文信息 " +  paper.getId());
        DrfPapers drfPapers = new DrfPapers();
        BeanUtils.copyProperties(paper, drfPapers);
        drfPapers.setUpdateTime(DateTime.now());
        drfPapersService.updateById(drfPapers);
        return Result.success("修改成功");
    }

    /**
     * 获取论文问题列表接口
     */
    @ApiOperation("获取论文问题列表")
    @GetMapping("/listProblem")
    public Result<List<problemVO>> listProblem() {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        log.info("学生端：获取论文问题列表");
        List<problemVO> problemVOList = new ArrayList<>();
        List<DrfProblem> drfProblemList = drfProblemService.listByStudentId(userId);
        for (DrfProblem drfProblem : drfProblemList) {
            problemVO problemVO = new problemVO();
            BeanUtils.copyProperties(drfProblem, problemVO);
            problemVOList.add(problemVO);
        }
        return Result.success(problemVOList);
    }

    /**
     * 修改问题状态为已知晓
     */
    @ApiOperation("根据问题id修改问题状态为已知晓")
    @PostMapping("/updateProblemStatus/{id}")
    public Result<String> updateProblemStatus(@PathVariable Integer id) {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：修改问题状态为已知晓 " + id);
        DrfProblem drfProblem = drfProblemService.getById(id);
        drfProblem.setKnow(1);
        drfProblemService.updateById(drfProblem);
        return Result.success("修改成功");
    }


    /**
     * 上传论文接口
     */
    @ApiOperation("上传论文")
    @PostMapping(value = "/uploadPaper")
    public Result<String> uploadPaper(@RequestBody paperDTO paper) {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：上传论文");
        DrfPapers drfPapers = new DrfPapers();
        //直接使用拷贝方法到drfPapers
        BeanUtils.copyProperties(paper, drfPapers);

        drfPapers.setStudentId(userId);
        drfPapers.setCreateBy(drfUsers.getRealName());
        drfPapers.setCreateTime(DateTime.now());
        drfPapers.setUpdateTime(DateTime.now());
        drfPapers.setStatus(papersStatus.SUBMIT);

        //生成论文id，JUWP+当前年+论文个数（以0001的格式）
        int count = (int) (drfPapersService.count() + 1);
        String paperId = "JUWP" + DateTime.now().toString("yyyy") + String.format("%04d", count);
        drfPapers.setId(paperId);

        drfPapersService.save(drfPapers);

        return Result.success("上传成功");
    }

    /**
     * 上传文件接口
     */
    @ApiOperation("上传文件")
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Integer> uploadFile(@RequestParam(value = "paperFile", required = false) MultipartFile paperFile,
                                      @RequestParam(value = "supportingFile", required = false) MultipartFile supportingFile,
                                      @RequestParam(value = "plagiarismCheckFile", required = false) MultipartFile plagiarismCheckFile,
                                      @RequestParam(value = "programFile", required = false) MultipartFile programFile) {
        try {
            //判断是否为学生
            String userId = String.valueOf(BaseContext.getCurrentId());
            DrfUsers drfUsers = drfUsersService.getById(userId);
            if (!drfUsers.getStatus().equals("student")) {
                return Result.error("请先登录学生账号");
            }
            log.info("学生端：上传文件");
            
            // 检查请求是否包含multipart内容
            if (paperFile == null && supportingFile == null && plagiarismCheckFile == null && programFile == null) {
                return Result.error("未检测到上传的文件");
            }
            
            //判断文件名是否为空与是否为pdf（仅检查上传了的文件）
            if (paperFile != null && (paperFile.getOriginalFilename() == null || !paperFile.getOriginalFilename().endsWith(".pdf"))) {
                return Result.error("请上传pdf文件");
            }
            
            //bucketName每一百篇论文放在一个bucketName下
            //获取查询论文文件表数量
            long count = drfFileService.count() + 100;
            String bucketName = "uploads" + (int)(count / 100);//获取bucketName
            
            String paperName = null;
            String paperFilename = null;
            if (paperFile != null && !paperFile.isEmpty()) {
                paperFilename = paperFile.getOriginalFilename();
                paperName = minIOService.uploadFile(paperFile, bucketName);
            }
            
            String supportingName = null;
            String supportingFilename = null;
            if (supportingFile != null && !supportingFile.isEmpty()) {
                supportingFilename = supportingFile.getOriginalFilename();
                supportingName = minIOService.uploadFile(supportingFile, bucketName);
            }
            
            String plagiarismCheckName = null;
            String plagiarismCheckFilename = null;
            if (plagiarismCheckFile != null && !plagiarismCheckFile.isEmpty()) {
                plagiarismCheckFilename = plagiarismCheckFile.getOriginalFilename();
                plagiarismCheckName = minIOService.uploadFile(plagiarismCheckFile, bucketName);
            }
            
            String programName = null;
            String programFilename = null;
            if (programFile != null && !programFile.isEmpty()) {
                programFilename = programFile.getOriginalFilename();
                programName = minIOService.uploadFile(programFile, bucketName);
            }

            DrfFile drfFile = new DrfFile();
            drfFile.setPaperName(paperFilename);
            drfFile.setPaperFile(paperName);
            drfFile.setSupportingName(supportingFilename);
            drfFile.setSupportingFile(supportingName);
            drfFile.setPlagiarismCheckName(plagiarismCheckFilename);
            drfFile.setPlagiarismCheckFile(plagiarismCheckName);
            drfFile.setProgramName(programFilename);
            drfFile.setProgramFile(programName);
            drfFile.setBucketName(bucketName);

            drfFileService.save(drfFile);

            return Result.success(drfFile.getId());
        } catch (org.springframework.web.multipart.MultipartException e) {
            log.error("文件上传失败，multipart解析异常: ", e);
            return Result.error("文件上传失败，请检查网络连接或稍后重试");
        } catch (Exception e) {
            log.error("文件上传失败: ", e);
            return Result.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 根据文件表id获取文件接口
     */
    @ApiOperation("根据文件表id获取文件")
    @GetMapping("/getFile/{fileId}")
    public Result<fileUrlVO> getFile(@PathVariable Integer fileId) {
        log.info("获取文件: " + fileId);
        DrfFile drfFile = drfFileService.getById(fileId);
        fileUrlVO fileUrlVO = new fileUrlVO();
        BeanUtils.copyProperties(drfFile, fileUrlVO);
        log.info("获取到bucket" + drfFile.getBucketName());
        fileUrlVO.setPaperURL(drfFile.getPaperFile() != null ? minIOService.getPresignedUrl(drfFile.getPaperFile(), drfFile.getBucketName(), 3600) : null);
        fileUrlVO.setSupportingURL(drfFile.getSupportingFile() != null ? minIOService.getPresignedUrl(drfFile.getSupportingFile(), drfFile.getBucketName(), 3600) : null);
        fileUrlVO.setPlagiarismCheckURL(drfFile.getPlagiarismCheckFile() != null ? minIOService.getPresignedUrl(drfFile.getPlagiarismCheckFile(), drfFile.getBucketName(), 3600) : null);
        fileUrlVO.setProgramURL(drfFile.getProgramFile() != null ? minIOService.getPresignedUrl(drfFile.getProgramFile(), drfFile.getBucketName(), 3600) : null);

        return Result.success(fileUrlVO);
    }

    /**
     * 修改文件接口
     */
    @Transactional
    @ApiOperation("修改文件")
    @PostMapping("/updateFile/{fileId}")
    public Result<String> updateFile(@RequestParam(value = "paperFile", required = false) MultipartFile paperFile,
                                     @RequestParam(value = "supportingFile", required = false) MultipartFile supportingFile,
                                     @RequestParam(value = "plagiarismCheckFile", required = false) MultipartFile plagiarismCheckFile,
                                     @RequestParam(value = "programFile", required = false) MultipartFile programFile,
                                     @PathVariable Integer fileId) {
        try {
            String userId = String.valueOf(BaseContext.getCurrentId());
            DrfUsers drfUsers = drfUsersService.getById(userId);
            if (!drfUsers.getStatus().equals("student")) {
                return Result.error("请先登录学生账号");
            }
            log.info("学生端：修改文件");
            
            // 检查请求是否包含multipart内容
            if (paperFile == null && supportingFile == null && plagiarismCheckFile == null && programFile == null) {
                return Result.error("未检测到上传的文件");
            }
            
            //根据id获取原文件
            DrfFile drfFile = drfFileService.getById(fileId);
            //传过来确实有文件时再进行修改与删除文件
            if(paperFile != null && !paperFile.isEmpty()){
                //先进行删除文件
                deleteFile(drfFile.getPaperFile(), drfFile.getBucketName());
                String paperName = paperFile.getOriginalFilename();
                String paperFileUrl = minIOService.uploadFile(paperFile, drfFile.getBucketName());
                drfFile.setPaperName(paperName);
                drfFile.setPaperFile(paperFileUrl);
            }
            if(supportingFile != null && !supportingFile.isEmpty()){
                deleteFile(drfFile.getSupportingFile(), drfFile.getBucketName());
                String supportingName = supportingFile.getOriginalFilename();
                String supportingFileUrl = minIOService.uploadFile(supportingFile, drfFile.getBucketName());
                drfFile.setSupportingName(supportingName);
                drfFile.setSupportingFile(supportingFileUrl);
            }
            if(plagiarismCheckFile != null && !plagiarismCheckFile.isEmpty()){
                deleteFile(drfFile.getPlagiarismCheckFile(), drfFile.getBucketName());
                String plagiarismCheckName = plagiarismCheckFile.getOriginalFilename();
                String plagiarismCheckFileUrl = minIOService.uploadFile(plagiarismCheckFile, drfFile.getBucketName());
                drfFile.setPlagiarismCheckName(plagiarismCheckName);
                drfFile.setPlagiarismCheckFile(plagiarismCheckFileUrl);
            }
            if(programFile != null && !programFile.isEmpty()){
                deleteFile(drfFile.getProgramFile(), drfFile.getBucketName());
                String programName = programFile.getOriginalFilename();
                String programFileUrl = minIOService.uploadFile(programFile, drfFile.getBucketName());
                drfFile.setProgramName(programName);
                drfFile.setProgramFile(programFileUrl);
            }
            drfFileService.updateById(drfFile);
            return Result.success("修改成功");
        } catch (org.springframework.web.multipart.MultipartException e) {
            log.error("文件修改失败，multipart解析异常: ", e);
            // 检查是否是客户端中断了上传
            if (isClientAbortException(e)) {
                log.info("客户端中断了文件上传: {}", e.getMessage());
                return Result.success("客户端取消了文件上传");
            }
            return Result.error("文件修改失败，请检查网络连接或稍后重试");
        } catch (Exception e) {
            log.error("文件修改失败: ", e);
            return Result.error("文件修改失败: " + e.getMessage());
        }
    }

    /**
     * 根据用户id获取论文状态
     *
     */
    @ApiOperation("获取论文状态")
    @PostMapping("/getPaperStatus")
    public Result<List<studentPaperVO>> getPaperStatus() {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：查询论文状态");

        //根据用户id获取论文表
        List<DrfPapers> drfPapers = drfPapersService.getPaperByUserId(userId);
        if(drfPapers.size() == 0){
            return Result.success(new ArrayList<>());
        }
        List<studentPaperVO> studentPaperVOS = new ArrayList<>();
        for (DrfPapers paper : drfPapers) {
            studentPaperVO studentPaperVO = new studentPaperVO();
           BeanUtils.copyProperties(paper, studentPaperVO);
           if (paper.getStatus().equals(papersStatus.EXPIRED)){
               studentPaperVO.setStatus(papersStatus.REVIEW);
           }
           if(paper.getStatus().equals(papersStatus.REVIEW_END)){//若审核结束，则存入相对应的审核意见id
               String[] opinionsId = drfIndividualReviewService.getOpinionsIdByPaperId(paper.getId());
               if (opinionsId.length < 2){
                   return Result.error("审核状态错误，请等待管理员处理");
               }
               studentPaperVO.setReviewOpinionsId1(opinionsId[0]);
               studentPaperVO.setReviewOpinionsId2(opinionsId[1]);
           }
           studentPaperVOS.add(studentPaperVO);
        }
        return Result.success(studentPaperVOS);
    }


    /**
     * 检查是否是客户端中断导致的异常
     * @param e Exception
     * @return boolean
     */
    private boolean isClientAbortException(Exception e) {
        Throwable cause = e.getCause();
        while (cause != null) {
            if (cause instanceof EOFException || 
                "java.io.EOFException".equals(cause.getClass().getName())) {
                return true;
            }
            cause = cause.getCause();
        }
        
        // 检查异常消息中是否包含特定的关键字
        String message = e.getMessage();
        if (message != null && (message.contains("EOFException") || 
                               message.contains("ClientAbort") || 
                               message.contains("Broken pipe"))) {
            return true;
        }
        
        return false;
    }

    /**
     * 若进行文件重新上传需要将上次文件删除
     */
    public void deleteFile(String objectName , String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        if (objectName == null || objectName.isEmpty()) {
            log.info("对象名为空，跳过删除操作");
            return;
        }
        
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

    /**
     * 接收公告
     */
    @ApiOperation("接收公告")
    @GetMapping("/studentNotice")
    public Result<List<DrfNotice>> acceptNotice() {
        String userId = String.valueOf(BaseContext.getCurrentId());
        DrfUsers drfUsers = drfUsersService.getById(userId);
        if (!drfUsers.getStatus().equals("student")) {
            return Result.error("请先登录学生账号");
        }
        log.info("学生端：接收公告");
        return Result.success(drfNoticeService.studentNotice());
    }
}